using DA.AnimGraph;
using System;
using System.Collections;
using System.Reflection;
using UnityEngine;
using UnityEngine.UIElements;


namespace DA.AnimGraph.Editor {
    internal static class InspectorFieldFactory {

        public static InspectorField SwitchField(Type fieldType) {
            // link
            if (fieldType == typeof(AGAFieldModel_FloatLink)) {
                var field = new InspectorField_FloatLink();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_IntLink)) {
                var field = new InspectorField_IntLink();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_Vector2Link)) {
                var field = new InspectorField_Vector2Link();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_ClipLink)) {
                var field = new InspectorField_ClipLink();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_MaskLink)) {
                var field = new InspectorField_MaskLink();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_MaskLink)) {
                var field = new InspectorField_MaskLink();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_Layer)) {
                var field = new InspectorField_Layer();
                return field;
            } else if (fieldType == typeof(AGAFieldModel_SequenceClipSlice)) {
                var field = new InspectorField_SequenceClipSlice();
                return field;
            }
            // perk
            else if (fieldType == typeof(AGAPerkModel_SyncGroup)) {
                var field = new InspectorField_SyncGroupPerk();
                return field;
            } else if (fieldType == typeof(AGAPerkModel_Timeline)) {
                var field = new InspectorField_TimelinePerk();
                return field;
            }
            // 基础类型
            else if (fieldType == typeof(RefField<string>)) {
                var field = new InspectorField_String();
                return field;
            } else if (fieldType == typeof(RefField<float>)) {
                var field = new InspectorField_Float();
                return field;
            } else if (fieldType == typeof(RefField<int>)) {
                var field = new InspectorField_Int();
                return field;
            } else if (fieldType == typeof(RefField<bool>)) {
                var field = new InspectorField_Bool();
                return field;
            } else if (fieldType == typeof(Action)) {
                var field = new InspectorField_Button();
                return field;
            }
            // enum
            else if (fieldType == typeof(RefField<AGABlackboardType>)) {
                var field = new InspectorField_BlackboardEntryType();
                return field;
            }
            // 通用枚举判定
            else if (IsRefFieldEnum(fieldType)) {
                var genericArgument = fieldType.GetGenericArguments()[0];
                var inspectorFieldEnumType = typeof(InspectorField_Enum<>).MakeGenericType(genericArgument); // 创建 InspectorField_Enum<T> 类型
                var field = Activator.CreateInstance(inspectorFieldEnumType) as InspectorField;
                return field;
            }
            return null;
        }

        static bool IsRefFieldEnum(Type fieldType) {
            // 条件 1：检查是否为泛型类型
            if (!fieldType.IsGenericType)
                return false;

            // 条件 2：检查是否为 RefField<T>
            var genericDefinition = fieldType.GetGenericTypeDefinition();
            if (genericDefinition != typeof(RefField<>))
                return false;

            // 条件 3：检查泛型参数是否为枚举
            var genericArgument = fieldType.GetGenericArguments()[0];
            return genericArgument.IsEnum;
        }

        public static ListView SwitchListField(string name, InspectorFieldAttribute attr, InspectorDataSource source, FieldInfo fieldInfo, AGEContext ageContext, Action saveCallback) {
            // 基本上用不上，列表形式的控件总是需要自定义各种东西
            Debug.Assert(typeof(IList).IsAssignableFrom(fieldInfo.FieldType));

            var elementType = fieldInfo.FieldType.GenericTypeArguments[0];
            var sourceList = fieldInfo.GetValue(source) as IList;

            ListView listView = new ListView() {
                name = name,
                headerTitle = name,
                reorderable = true,
                reorderMode = ListViewReorderMode.Animated,
                fixedItemHeight = 160,
                selectionType = SelectionType.Single,
                showAlternatingRowBackgrounds = AlternatingRowBackground.All,
                showFoldoutHeader = true,
                showBorder = true,
                //showAddRemoveFooter = true,
            };
            listView.itemsSource = fieldInfo.GetValue(source) as IList;
            listView.itemIndexChanged += (oldIndex, newIndex) => {
                listView.Rebuild();
            };
            listView.makeItem = () => {
                var field = SwitchField(elementType);
                return field;
            };
            listView.bindItem = (element, index) => {
                if (element is InspectorField field) {
                    field.Init($"[{index}]", sourceList[index], ageContext, saveCallback);
                }
            };

            listView.Q<TextField>("unity-list-view__size-field").isReadOnly = true;
            return listView;
        }

        /// <summary>
        /// ListViewAGE 使用示例
        /// </summary>
        private static VisualElement BuildInputPortList2(string name, InspectorFieldAttribute fieldAttribute, InspectorDataSource source, FieldInfo fieldInfo, AGEContext ageContext, Action saveCallback) {
            var sourceList = fieldInfo.GetValue(source) as IList;

            var listView = new ListViewAGE() {
                title = name,
                enableCountController = true,
                itemsSource = sourceList,
            };

            listView.makeItem = () => {
                var w = new InlineWrapper();
                w.upButtonClicked += (index) => {
                    var tmp = sourceList[index];
                    sourceList[index] = sourceList[index - 1];
                    sourceList[index - 1] = tmp;
                    listView.Rebuild();
                    saveCallback?.Invoke();
                };
                w.downButtonClicked += (index) => {
                    var tmp = sourceList[index];
                    sourceList[index] = sourceList[index + 1];
                    sourceList[index + 1] = tmp;
                    listView.Rebuild();
                    saveCallback?.Invoke();
                };
                w.deleteButtonClicked += (index) => {
                    sourceList.RemoveAt(index);
                    listView.Rebuild();
                    saveCallback?.Invoke();
                };
                return (new InspectorField_InputPort(), w);
            };

            listView.bindItem = (element, wrapper, index) => {
                if (element is InspectorField_InputPort field) {
                    field.Init(null, sourceList[index], ageContext, saveCallback);
                }
                if (wrapper is InlineWrapper w) {
                    w.index = index;
                    w.text = $"[{index}]";
                    //w.enableUp = index > 1;
                    //w.enableDown = index > 0 && index < sourceList.Count - 1;
                    //w.enableDelete = index != 0 && sourceList.Count > 2;
                }
            };

            listView.addButtonClicked = () => {
                sourceList.Add(new AGAFieldModel_InputPort("new port"));
                listView.Rebuild();
                saveCallback?.Invoke();
            };

            return listView;
        }
    }
}
